using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;

namespace SCADAEditor.Component
{
    /// <summary>
    /// 组件基类，定义所有组态软件组件共有的属性和方法，INotifyPropertyChanged这个将使所有继承自 ComponentBase 的组件都能支持属性变更通知功能。
    /// </summary>
    public abstract class ComponentBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        private bool _isSelected = false;

        /// <summary>
        /// 获取或设置组件是否被选中
        /// </summary>
        [Category("状态")]
         public bool IsSelected 
        {
            get => _isSelected;
            set 
            { 
                _isSelected = value;
                OnPropertyChanged();
            }
        }

        /// <summary>
        /// 组件唯一标识符
        /// </summary>
         [Category("基本属性")]
          public string Id { get; set; }

        /// <summary>
        /// 组件显示名称
        /// </summary>
       [Category("基本属性")]
        public string Name { get; set; }

        /// <summary>
        /// 组件在容器中的位置坐标
        /// </summary>
        [Category("位置和大小")]
         public Point Position { get; set; }

        /// <summary>
        /// 组件尺寸
        /// </summary>
         [Category("位置和大小")]
         public Size Size { get; set; }

        /// <summary>
        /// 绘制组件到指定的Graphics对象
        /// </summary>
        /// <param name="g">绘图表面</param>
        public abstract void Draw(Graphics g);

        /// <summary>
        /// 将组件状态序列化为JSON字典
        /// </summary>
        /// <returns>包含组件状态的字典</returns>
        public virtual Dictionary<string, object> ToJson()
        {
            var dict = new Dictionary<string, object>();
            dict.Add("Id", Id);
            dict.Add("Name", Name);
            dict.Add("PositionX", Position.X);
            dict.Add("PositionY", Position.Y);
            dict.Add("Width", Size.Width);
            dict.Add("Height", Size.Height);
            dict.Add("Text", Text);
            dict.Add("BackColor", BackColor.ToArgb());
            dict.Add("IsEditMode", IsEditMode);
            dict.Add("IsSelected", IsSelected);
            return dict;
        }

        /// <summary>
        /// 从JSON字典恢复组件状态
        /// </summary>
        /// <param name="json">包含组件状态的字典</param>
       public virtual void FromJson(Dictionary<string, object> json)
        {
            Id = (string)json["Id"];
            Name = (string)json["Name"];
            Position = new Point(Convert.ToInt32(json["PositionX"]), Convert.ToInt32(json["PositionY"]));
            Size = new Size(Convert.ToInt32(json["Width"]), Convert.ToInt32(json["Height"]));
            Text = (string)json["Text"];
            BackColor = Color.FromArgb((int)json["BackColor"]);
            IsEditMode = (bool)json["IsEditMode"];
            IsSelected = (bool)json["IsSelected"];
        }

        /// <summary>
        /// 创建组件的深拷贝
        /// </summary>
        public virtual ComponentBase Clone()
        {
            var clone = (ComponentBase)this.MemberwiseClone();
            clone.Id = Guid.NewGuid().ToString(); // 为新实例生成新ID
            return clone;
        }
    
        private string _text = string.Empty;
        private Color _backColor = SystemColors.Control;
    
        /// <summary>
        /// 组件显示文本
        /// </summary>
        [Category("外观")]
        public string Text 
        {
            get => _text;
            set { _text = value; OnPropertyChanged(); }
        }
        
        /// <summary>
        /// 组件背景色
        /// </summary>
        [Category("外观")]
        public Color BackColor 
        {
            get => _backColor;
            set { _backColor = value; OnPropertyChanged(); }
        }
    
        /// <summary>
        /// 属性变更通知方法
        /// </summary>
        protected virtual void OnPropertyChanged()
        {
            // 可以在这里添加属性变更通知逻辑
            // 例如触发重绘或通知观察者
        }
    
        private bool _isEditMode = false;
        
        /// <summary>
        /// 获取或设置组件是否处于编辑状态
        /// </summary>
         [Category("状态")]
         public bool IsEditMode 
        {
            get => _isEditMode;
            set 
            { 
                _isEditMode = value;
                OnPropertyChanged();
            }
        }
    
        /// <summary>
        /// 检查点是否在组件边界内
        /// </summary>
        public virtual bool HitTest(Point point)
        {
            return new Rectangle(Position, Size).Contains(point);
        }
    
        /// <summary>
        /// 绘制编辑状态下的控制点
        /// </summary>
        protected virtual void DrawEditControls(Graphics g)
        {
           if (!IsEditMode || !IsSelected) return;
            
            const int handleSize = 8;
            var rect = new Rectangle(Position, Size);
            
            // 定义8个控制点的位置
            var handles = new[]
            {
                // 四个角点
                new Rectangle(rect.Left - handleSize/2, rect.Top - handleSize/2, handleSize, handleSize),    // 左上
                new Rectangle(rect.Right - handleSize/2, rect.Top - handleSize/2, handleSize, handleSize),   // 右上
                new Rectangle(rect.Left - handleSize/2, rect.Bottom - handleSize/2, handleSize, handleSize),  // 左下
                new Rectangle(rect.Right - handleSize/2, rect.Bottom - handleSize/2, handleSize, handleSize), // 右下
                
                // 四个边中点
                new Rectangle(rect.Left + rect.Width/2 - handleSize/2, rect.Top - handleSize/2, handleSize, handleSize),     // 上中
                new Rectangle(rect.Left + rect.Width/2 - handleSize/2, rect.Bottom - handleSize/2, handleSize, handleSize),  // 下中
                new Rectangle(rect.Left - handleSize/2, rect.Top + rect.Height/2 - handleSize/2, handleSize, handleSize),    // 左中
                new Rectangle(rect.Right - handleSize/2, rect.Top + rect.Height/2 - handleSize/2, handleSize, handleSize)    // 右中
            };

            using (var brush = new SolidBrush(Color.White))
            using (var pen = new Pen(Color.Blue))
            {
                foreach (var handle in handles)
                {
                    g.FillRectangle(brush, handle);
                    g.DrawRectangle(pen, handle);
                }
            }
        }
    }
}